package com.sure.minion.services.base.handler;

import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.sure.minion.services.base.handler.exception.DefaultAutoHandledException;
import com.sure.minion.services.base.utils.StringUtil;

/**
 * @Description 本类中定义了描述和信息组（描述组）的映射 描述组包括三个内容：一个信息码，一个用户友好的描述，一个开发者友好的描述
 * 
 *              包括的方法： 直接从描述取描述组 从信息码取到用户友好的描述 从信息码取到开发者友好的描述 判断一个信息码是否是一个指定的描述的含义（如1是SUCCESS）
 * @author syuan
 * @date 2015年8月28日 下午1:41:12 Company: TravelSky
 */
@Component
public class ResponseDefinitionFactory {
	/** 分隔符 */
	private static final String SEPERATOR = "@";

	/**
	 * 如果传入的错误码没有定义，会调用下面的非法定义 之所以写在这里是因为这里不用配置，即使错了也不至于使程序崩溃
	 */
	private static final String INVALID_DESCRIPTION = "INVALID_DESCRIPTION";

	/** 未处理错误编码 */
	private static final String INVALID_MESSAGE_CODE = "-0000";

	/** 未处理用户描述 */
	private static final String INVALID_USER_HINT = "未知错误，请联系管理员";

	/** 未处理日志描述 */
	private static final String INVALID_SYSTEM_LOG = "未处理的异常错误信息";

	/**
	 * @Fields properties 异常描述信息配置文件
	 * @date 2015年2月6日 下午8:03:24
	 */
	private static ResourceBundle properties = ResourceBundle.getBundle("messages/Messages", Locale.CHINA);

	/**
	 * 错误描述对应一组错误定义（错误代码，写在日志的错误信息，用户可见的错误描述）
	 */
	private static Map<String, DescriptionGroup> descriptionToDescriptionGroup = new ConcurrentHashMap<String, DescriptionGroup>();

	/**
	 * 错误代码对应错误描述的map，方便反向查找信息
	 */
	private static Map<String, String> messageCodeToDescription = new ConcurrentHashMap<String, String>();

	private static Logger logger = LoggerFactory.getLogger(ResponseDefinitionFactory.class);

	public ResponseDefinitionFactory() {
		DescriptionGroup descriptionGroup = new DescriptionGroup(INVALID_MESSAGE_CODE,
				INVALID_USER_HINT, INVALID_SYSTEM_LOG);
		descriptionToDescriptionGroup.put(INVALID_DESCRIPTION, descriptionGroup);
		messageCodeToDescription.put(INVALID_MESSAGE_CODE, INVALID_DESCRIPTION);
	}

	/**
	 * @Description 初始化错误信息-当DI容器实例化当前受管Bean时，自动触发方法
	 * @date 2015年2月6日 下午8:03:55
	 */
	@PostConstruct
	private void initProperties() {
		Enumeration<String> keys = properties.getKeys();
		while(keys.hasMoreElements()) {
			String key = keys.nextElement();
			String[] strs = properties.getString(key).split(SEPERATOR);
			DescriptionGroup descriptionGroup = null;
			try {
				descriptionGroup = new DescriptionGroup(strs[0], strs[1], strs[2]);// 错误码，用户描述，log描述
			} catch(IndexOutOfBoundsException e) {
				logger.error("异常：{}格式错误", key);
				throw e;
			}
			descriptionToDescriptionGroup.put(key, descriptionGroup);
			messageCodeToDescription.put(strs[0], key);
		}
		logger.info("--------------异常信息描述初始化完成----------\n" + descriptionToDescriptionGroup);
	}

	/**
	 * @Description 根据异常实例-获取异常信息描述信息及日志信息
	 * @param defaultAutoHandledException
	 * @return
	 * @date 2015年2月6日 下午8:05:06
	 */
	public static DescriptionGroup getDescriptionGroup(DefaultAutoHandledException defaultAutoHandledException) {
		
		if (descriptionToDescriptionGroup.containsKey(defaultAutoHandledException.getDescription())) {
			
			DescriptionGroup descriptionGroup = descriptionToDescriptionGroup.get(defaultAutoHandledException.getDescription());
			
			DescriptionGroup descNew = new DescriptionGroup(descriptionGroup.getMessageCode(),
					descriptionGroup.getUserhint(), descriptionGroup.getSystemLog());
			
			if (defaultAutoHandledException.getParams() != null
					&& defaultAutoHandledException.getParams().length > 0) {
				descNew.setSystemLog(StringUtil.format(descriptionGroup.getSystemLog(),
						defaultAutoHandledException.getParams()));
				descNew.setUserhint(StringUtil.format(descriptionGroup.getUserhint(),
						defaultAutoHandledException.getParams()));
			}
			
			return descNew;
		}
		
		logger.warn("无此异常key对应的描述信息：" + defaultAutoHandledException.getDescription());
		
		return descriptionToDescriptionGroup.get(INVALID_DESCRIPTION);
	}

	/**
	 * @Description 根据错误代码-获取异常信息描述信息及日志信息
	 * @param description
	 * @return
	 * @date 2015年2月6日 下午8:05:56
	 */
	public static DescriptionGroup getDescriptionGroup(String description) {
		if (descriptionToDescriptionGroup.containsKey(description)) {
			return descriptionToDescriptionGroup.get(description);
		}
		
		logger.warn("无此异常key对应的描述信息：" + description);
		
		return descriptionToDescriptionGroup.get(INVALID_DESCRIPTION);
	}

	/**
	 * @Description 获取错误代码
	 * @param description
	 * @return
	 * @date 2015年2月6日 下午8:06:51
	 */
	public static String getMessageCode(String description) {
		DescriptionGroup descriptionGroup = getDescriptionGroup(description);
		return descriptionGroup.getMessageCode();
	}

}
